package com.xiaoxin.experience.service.helper;

import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xiaoxin
 */
@Service
public class HelperService
{
    private final Pattern FIELD_NAME_PATTERN = Pattern.compile("name=\"(.*?)\"");

    private final Pattern FIELD_TYPE_PATTERN = Pattern.compile("type=\"(.*?)\"");

    private final Pattern FIELD_FIXED_PATTERN = Pattern.compile("fixed=\"(.*?)\"");

    private String[] gbXmlPreHandle(String gbXml)
    {
        gbXml = gbXml.replace("\n","");
        return gbXml.split("/");
    }

    public String handleGBXmlForJson(String gbXml)
    {
        String[] strings = gbXmlPreHandle(gbXml);
        if (strings.length == 0)
        {
            return "{}";
        }
        StringBuilder result = new StringBuilder("{\n");
        for (String s : strings)
        {
            String filedForJson = handleFiledForJson(s);
            if ("".equals(filedForJson))
            {
                continue;
            }
            result.append("    ");
            result.append(filedForJson);
            result.append(",\n");
        }
        String string = result.toString();
        string = string.substring(0,string.lastIndexOf(","));
        return string + "\n}";
    }

    private String handleFiledForJson(String field)
    {
        String filedName = getFiledName(field);
        String filedType = getFiledType(field);
        if (Objects.isNull(filedName))
        {
            return "";
        }
        if ("integer".equals(filedType))
        {
            return "\""+ firstCharToLower(filedName) +"\":" + "1";
        }
        else
        {
            return "\""+ firstCharToLower(filedName) +"\":" + "\"" + filedType +"\"";
        }
    }

    public String handleGbXmlForSetter(String gbXml,String objName,String elementName)
    {
        String[] strings = gbXmlPreHandle(gbXml);
        if (strings.length == 0)
        {
            return "";
        }
        StringBuilder result = new StringBuilder();
        for (String s : strings)
        {
            result.append(handleFiledForSetter(s,objName,elementName));
        }
        return result.toString();
    }

    private String handleFiledForSetter(String field,String objName,String elementName)
    {
        String filedName = getFiledName(field);
        String type = getFiledType(field);
        if (Objects.isNull(filedName) || Objects.isNull(type))
        {
            return "";
        }
        if ("integer".equals(type))
        {
            return objName + ".set" + filedName + "(Integer.valueOf(XmlUtil.getText("+ elementName +",\""+filedName+"\")));\n";
        }
        return objName + ".set" + filedName + "(XmlUtil.getText("+ elementName +",\""+filedName+"\"));\n";
    }

    public String handleGbXmlToFiled(String gbXml)
    {
        String[] split = gbXmlPreHandle(gbXml);
        if (split.length == 0)
        {
            return "";
        }
        StringBuilder result = new StringBuilder();
        for (String s : split)
        {
            result.append(handleFiled(s));
        }
        return result.toString();
    }

    private String handleFiled(String field)
    {
        String comment = getComment(field);
        String filedName = getFiledName(field);
        String type = getFiledType(field);
        String fixed = getFixed(field);
        String handleResult = "";
        if (Objects.isNull(filedName))
        {
            return handleResult;
        }
        if (Objects.nonNull(comment))
        {
            handleResult += "    /**\n" + "     * "+ comment +"\n" + "     */\n";
        }
        if (field.contains("attribute"))
        {
            handleResult += "    @Attribute(name = \""+ filedName +"\",required = false)\n";
        }
        else
        {
            handleResult += "    @Element(name = \""+ filedName +"\",required = false)\n";
        }
        if (Objects.nonNull(type))
        {
            handleResult += "    private "+firstCharToUpper(type)+" "+ firstCharToLower(filedName) +";\n\n";
        }
        else
        {
            handleResult += "    private String "+ firstCharToLower(filedName) +" = \"" + fixed +"\";\n\n";
        }
        return handleResult;
    }

    private String firstCharToUpper(String s)
    {
        return s.substring(0,1).toUpperCase() + s.substring(1);
    }

    private String firstCharToLower(String s)
    {
        return s.substring(0,1).toLowerCase() + s.substring(1);
    }

    private String getComment(String field)
    {
        String comment = null;
        int commentStart = getCommentStart(field);
        if (commentStart != -1)
        {
            int commentEnd = getCommentEnd(field);
            comment = field.substring(commentStart,commentEnd);
        }
        return comment;
    }

    private String getFiledName(String field)
    {
        Matcher matcher = FIELD_NAME_PATTERN.matcher(field);
        if (matcher.find())
        {
            return matcher.group().replace("name=\"","").replace("\"","");
        }
        return null;
    }

    private String getFiledType(String field)
    {
        Matcher matcher = FIELD_TYPE_PATTERN.matcher(field);
        if (matcher.find())
        {
            return matcher.group().replace("type=\"","").replace("\"","");
        }
        return null;
    }

    private String getFixed(String field)
    {
        Matcher matcher = FIELD_FIXED_PATTERN.matcher(field);
        if (matcher.find())
        {
            return matcher.group().replace("fixed=\"","").replace("\"","");
        }
        return null;
    }

    private int getCommentStart(String field)
    {
        String[] pattern = {"<!--","<!-"};
        for (String s : pattern)
        {
            if (field.contains(s))
            {
                return field.indexOf(s) + s.length();
            }
        }
        return -1;
    }


    private int getCommentEnd(String field)
    {
        String[] pattern = {"-->","--)","->","-)","一>"};
        for (String s : pattern)
        {
            if (field.indexOf(s) > 0)
            {
                return field.indexOf(s);
            }
        }
        return field.lastIndexOf("-");
    }
}
